package com.gome.ocean.service.utils.job;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gome.ocean.common.constants.Constants;
import com.gome.ocean.common.enums.job.JobLimit;
import com.gome.ocean.common.enums.job.Reader;
import com.gome.ocean.common.enums.job.Writer;
import com.gome.ocean.common.exception.JobCreateException;
import com.gome.ocean.dao.model.authority.User;
import com.gome.ocean.dao.model.datax.CreateJobVO;

/**
 * Created by liuqingxia on 2016/1/28.
 */
public class CreateJobUtils {

    private static final Logger LOG                = LoggerFactory.getLogger(CreateJobUtils.class);
    private static String       READER_PACKAGE_PRE = "com.gome.ocean.service.utils.job.reader.";
    private static String       WRITER_PACKAGE_PRE = "com.gome.ocean.service.utils.job.writer.";
    private static String       READER_PACKAGE_SUF = "Reader";
    private static String       WRITER_PACKAGE_SUF = "Writer";
    private static String[]     CREATE_JOB_FIELDS  = new String[] { "reader", "writer", "submit_user", "submit_ip",
                                                                    "cronExpression", "projectId", "pipelineName",
                                                                    "jobLimit", "limitValue", "introduce",
                                                                    "executeType" };

    public static CreateJobVO getJobVO(HttpServletRequest req, String ipaddr) throws Exception {
        Field[] fields = CreateJobVO.class.getDeclaredFields();
        req.getParameterNames();
        CreateJobVO createJobVO = new CreateJobVO();
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            if (!isNeedField(fieldName)) {
                continue;
            }
            if ("jobLimit".equals(fieldName)) {
                String speedLimitTypeStr = req.getParameter("speedLimitType");
                if (StringUtils.isBlank(speedLimitTypeStr)) {
                    throw new IllegalArgumentException("参数speedLimitType不能为空");
                }
                int jobLimitValue = Integer.valueOf(speedLimitTypeStr);
                if (jobLimitValue < 0 || jobLimitValue > 1) {
                    throw new IllegalArgumentException("参数speedLimitType的值应在[0,1]之间");
                }
                JobLimit jobLimit = JobLimit.getJobLimit(jobLimitValue);
                createJobVO.setJobLimit(jobLimit);
                continue;
            }
            if ("executeType".equals(fieldName)) {
                String executeTypeStr = req.getParameter("executeType");
                if (StringUtils.isBlank(executeTypeStr)) {
                    throw new IllegalArgumentException("参数executeType不能为空");
                }
                int executeType = Integer.valueOf(executeTypeStr);
                createJobVO.setExecuteType(executeType);
                continue;
            }
            if ("limitValue".equals(fieldName)) {
                String speedLimitValue = req.getParameter("speedLimitValue");
                if (StringUtils.isBlank(speedLimitValue)) {
                    throw new IllegalArgumentException("参数speedLimitValue不能为空");
                }
                long limitValue = Long.valueOf(speedLimitValue);
                createJobVO.setLimitValue(limitValue);
                continue;
            }
            if ("submit_user".equals(fieldName)) {
                User user = (User) req.getSession().getAttribute(Constants.SESSION_LOGIN_USER);
                String email = user.getEmail();
                createJobVO.setSubmit_user(email);
                continue;
            }
            if ("reader".equals(fieldName)) {
                String readerStr = req.getParameter("readerType");
                if (StringUtils.isBlank(readerStr)) {
                    LOG.error("参数reader为空");
                    throw new IllegalArgumentException("参数reader不能为空");
                } else {
                    int readerInt = Integer.parseInt(readerStr);
                    if (readerInt < 0) {
                        throw new IllegalArgumentException("readerInt参数有误");
                    }
                    Reader reader = Reader.getReader(readerInt);
                    createJobVO.setReader(reader);
                    Map<String, Object> readerMaps = getReaderMap(req, Reader.getString(reader));
                    createJobVO.setReaderMaps(readerMaps);
                    continue;
                }
            }
            if ("writer".equals(fieldName)) {
                String writerStr = req.getParameter("writerType");
                if (StringUtils.isBlank(writerStr)) {
                    LOG.error("参数writer为空");
                    throw new IllegalArgumentException("参数writer不能为空");
                } else {
                    int writerInt = Integer.parseInt(writerStr);
                    if (writerInt < 0 || writerInt > 6) {
                        LOG.error("参数writerInt不在（0~6）");
                        throw new IllegalArgumentException("参数writerInt不在（0~6）");
                    }
                    Writer writer = Writer.getName(writerInt);
                    createJobVO.setWriter(writer);
                    Map<String, Object> writerMaps = getWriterMap(req, Writer.getString(writer));
                    createJobVO.setWriterMaps(writerMaps);
                    continue;
                }
            }
            if ("submit_ip".equals(fieldName)) {
                createJobVO.setSubmit_ip(ipaddr);
                continue;
            }
            if ("pipelineName".equals(fieldName)) {
				String projectName = req.getParameter("pipelineName");
				createJobVO.setProject(projectName);
				continue;
			}
            if ("projectId".equals(fieldName)) {
                String projectIdStr = req.getParameter("projectId");
                if (StringUtils.isBlank(projectIdStr)) {
                    LOG.error("参数projectId为空");
                    throw new IllegalArgumentException("参数projectId不能为空");
                } else {
                    Long projectId = Long.valueOf(projectIdStr);
                    createJobVO.setProjectId(projectId);
                }
                continue;
            }
            String fieldValue = req.getParameter(fieldName);
            String methodName = getSetMethodName(fieldName);
            Method set = null;
            try {
                set = CreateJobVO.class.getMethod(methodName, String.class);
                set.invoke(createJobVO, fieldValue);
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
                throw new JobCreateException(e.getMessage());
            }

        }
        return createJobVO;
    }

    private static String getSetMethodName(String pre) {
        String suffix = String.valueOf(pre.charAt(0)).toUpperCase() + pre.substring(1);
        String methodName = "set" + suffix;
        return methodName;
    }

    private static Map<String, Object> getReaderMap(HttpServletRequest req, String reader) {
        Map<String, Object> readerMaps = null;
        String readerClassName = READER_PACKAGE_PRE + addSuffix(reader, READER_PACKAGE_SUF);
        Class readerClass = null;
        try {
            readerClass = Class.forName(readerClassName);
            Method getReaderMap = readerClass.getDeclaredMethod("getReaderMap", HttpServletRequest.class);
            readerMaps = (Map<String, Object>) getReaderMap.invoke(readerClass, req);
        } catch (ClassNotFoundException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("未找到对应的reader插件类");
        } catch (NoSuchMethodException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("对应的reader插件类中并没有geReaderMap方法");
        } catch (InvocationTargetException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("创建Job发生异常，异常信息为：" + e.getTargetException().getMessage());
        } catch (IllegalAccessException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("对应reader插件类的getReaderMap方法不允许访问");
        }
        return readerMaps;
    }

    private static Map<String, Object> getWriterMap(HttpServletRequest req, String writer) {
        Map<String, Object> writerMaps;
        String writerClassName = WRITER_PACKAGE_PRE + addSuffix(writer, WRITER_PACKAGE_SUF);
        Class writerClass;
        try {
            writerClass = Class.forName(writerClassName);
            Method getWriterMap = writerClass.getDeclaredMethod("getWriterMap", HttpServletRequest.class);
            writerMaps = (Map<String, Object>) getWriterMap.invoke(null, req);
        } catch (ClassNotFoundException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("未找到对应的writer插件类");
        } catch (NoSuchMethodException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("对应的writer插件类中并没有getWriterMap方法");
        } catch (InvocationTargetException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("创建Job发生异常，异常信息为：" + e.getTargetException().getMessage());
        } catch (IllegalAccessException e) {
            LOG.error(e.getMessage(), e);
            throw new JobCreateException("对应writer插件类的getWriterMap方法不允许访问");
        }
        return writerMaps;
    }

    public static String addPrefix(String pre, String str) {
        if (StringUtils.isBlank(str)) {
            throw new IllegalArgumentException("参数str不能为空");
        }
        if (StringUtils.isBlank(pre)) {
            throw new IllegalArgumentException("参数pre不能为空");
        }
        str = firstLetter2Upper(str);
        String addPre = pre + str;
        return addPre;
    }

    public static String firstLetter2Upper(String str) {
        if (StringUtils.isBlank(str)) {
            throw new IllegalArgumentException("参数str不能为空");
        }
        str = String.valueOf(str.charAt(0)).toUpperCase() + str.substring(1);
        return str;
    }

    public static String addSuffix(String str, String suf) {
        if (StringUtils.isBlank(str)) {
            throw new IllegalArgumentException("参数str不能为空");
        }
        if (StringUtils.isBlank(suf)) {
            throw new IllegalArgumentException("参数suf不能为空");
        }
        str = firstLetter2Upper(str);
        String addSuf = str + suf;
        return addSuf;
    }

    private static Boolean isNeedField(String field) {
        for (String containField : CREATE_JOB_FIELDS) {
            if (containField.equals(field)) {
                return true;
            }
        }
        return false;
    }

}
